
#include "FwRule.h"


/*******************************************************
 Name: fwrules_parser                                       
 Copyright(c):                                         
   Ubaidul Khan, Information Security & Assurance                                
   George Mason University                             
   ISA-564(Spring), Apr 5, 2013                                       
*******************************************************/

/************************************************************
  These variables are used to parse the xml nodes read from
  the xml file
************************************************************/
char *uid, *coment, *ipv, *proto, *srcIP, *srcPort, *dstIP, 
     *dstPort, *action, *logPacket;

int location, xmlNodeHead, xmlNodeTail, uidFound, comentFound, 
    protoFound, srcPortFound, srcIPFound, dstPortFound, dstIPFound, 
    ipvFound, actionFound, logPacketFound, nodeFullyParsed;
    
int ruleCount = 0;


/************************************************************
  initGlobs - this function is used to initialize the variables
  mentioned above
************************************************************/
void initGlobs()
{
  uid = coment = proto = ipv = srcIP = srcPort = dstIP = 
        dstPort = action = logPacket = NULL;
     
  location = xmlNodeHead = xmlNodeTail = uidFound = comentFound = 
     protoFound = srcPortFound = srcIPFound = dstPortFound = 
     dstIPFound = ipvFound = logPacketFound = nodeFullyParsed = 0;
}

/************************************************************
  destroyGlobs - this function is used to free memory allocated
  for variables parsed from each XML node
************************************************************/
void destroyGlobs()
{
  free( proto ); free( ipv ); 
  free( srcIP ); free( srcPort ); free( dstIP ); free( dstPort ); free( action ); 
  free( logPacket);
}

/************************************************************
  This function is used to print he list of rules
************************************************************/
void printList(fwRuleList *myList)
{
  printf("<---- Executing printList ----\n");

  fwRuleNode *temp;
     
  temp = myList->head;
     
  while(temp != NULL)
  {
    printf("\n\t temp->location: %d\n", temp->location);
    printf("\n\t temp->uid: %s\n", temp->uid);
    printf("\n\t temp->coment: %s\n", temp->coment);
    printf("\n\t temp->ipv: %d\n", temp->ipv);
    printf("\n\t temp->dPort: %d\n", temp->dPort);
    printf("\n\t temp->srcIP: %s\n", temp->srcIP);
    printf("\n\t temp->sPort: %d\n", temp->sPort);
    printf("\n\t temp->dstIP: %s\n", temp->dstIP);
    printf("\n\t temp->proto: %s\n", temp->proto);
    printf("\n\t temp->actioin: %s\n", temp->action);
    printf("\n\t temp->log: %s\n", temp->log);
    printf("---------------------------------------------\n");
    temp = temp->next;

  }

}

/************************************************************
  This function initializes the fwRuleList by 
  creating a head node
************************************************************/
int initFWRULES(fwRuleList *list, fwRuleNode* head)
{
  // printf("<---- Executing initFWRULES ----\n");
  
    if(list == NULL)
    {
        return -1;
    }
    if(head == NULL)
    {
        return -1;
    }
     
    list->head = head;
     
    head->prev = NULL;
    head->next = NULL;
     
    return 1;
}

/************************************************************
  This function adds a node to the linked list. The node is
  pre-populated and sent as an argument, and this function
  create does the linking.
************************************************************/
int addToList(fwRuleList **myList, fwRuleNode **myNode)
{
  /*
  printf("<---- Executing addToList ----\n");
  printf("\n\t myNode->location: %d\n", myNode->location);
  printf("\n\t myNode->ipv: %d\n", myNode->ipv);
  printf("\n\t myNode->dPort %d\n", myNode->dPort);
  printf("\n\t myNode->ipv: %d\n", myNode->ipv);
  printf("\n\t myNode->srcIP: %s\n", myNode->srcIP);
  printf("\n\t myNode->sPort %d\n", myNode->sPort);
  printf("\n\t myNode->dstIP: %s\n", myNode->dstIP);
  printf("\n\t myNode->proto: %s\n", myNode->proto);
  printf("\n\t myNode->actioin: %s\n", myNode->action);
  printf("\n\t myNode->log: %s\n", myNode->log);
  */
  
  //Vars
  fwRuleNode *temp;
     
  //Checks
  if(myList == NULL)
  {
    printf("\n\tThe list is NULL");
    return -1;
  }
  if(myNode == NULL)
  {
    printf("\n\tThe list is NULL");
    return -1;
  }

  if(((*myList))->head == NULL)
  {
    printf("\n\tUnable to locate the head of the list");
    return -1;
  }
  
  //Move to the end of the list
  temp = ( (*myList))->head;
    
  while(temp->next != NULL)
  {
    // printf("\n\t temp->location: %d\n", temp->location);
    temp = temp->next;
  }
  
  //Set the links
  temp->next = *myNode;
  ((*myNode))->prev = temp;
  return 0;
}

/************************************************************
  This function removes any empty nodes from the list
************************************************************/
int cleanUpList(fwRuleList **myList, fwRuleNode **head)
{
   printf("<---- Executing cleanUpList ----\n");

  if(((*myList))->head == NULL)
  {
    printf("\n\tUnable to locate the head of the list");
    return -1;
  }
  
  fwRuleNode *nodeToDel;
  nodeToDel = ( (*myList))->head;

    
  while(nodeToDel->next != NULL)
  {
    // printf("\n\t temp->location: %d\n", temp->location);
    if( (nodeToDel->ipv == 0) && (nodeToDel->dPort == 0) && 
        (nodeToDel->sPort == 0) && (nodeToDel->srcIP == NULL) &&
        (nodeToDel->dstIP == NULL) && (nodeToDel->proto == NULL) &&
        (nodeToDel->action == NULL) && (nodeToDel->log == NULL)
      ) 
    {  
      if(nodeToDel == *head) {
        printf("\n\tAdjust head - removing empty node\n");
        nodeToDel = *head;
        *head = nodeToDel->next;
        ((*head))->prev = NULL;
        free(nodeToDel);
      }
      else {
        printf("\n\tRemoving empty node\n");
        nodeToDel->prev->next = nodeToDel->next;
        nodeToDel->next->prev = nodeToDel->prev;
        free(nodeToDel);
      }
    }
    
    nodeToDel = nodeToDel->next;
  }
  
  return 0;
}

/************************************************************
  This function is the heart of the parser - it is repeatedly
  called with XML data and it inspects the data and performs
  the appropriate task.
************************************************************/
void parseXML(int nodeDepth, xmlChar *nodeName, xmlChar *nodeValue, fwRuleList **myList)
{
  // printf("\n<------------ Executing parseXML ------------\n");

 /*  
  printf("\n\tProcessing rule #: %d\n\n", ruleCount);  
  printf("\tNode depth is: %d\n", nodeDepth);
  printf("\tNode name is: %s\n", nodeName);
  printf("\tNode value is: %s\n", nodeValue);

  printf("\tXML Node Head Found: %d\n", xmlNodeHead);
  printf("\tXML Node Tail Found: %d\n", xmlNodeTail);
  
  printf("\tsrcPortFound: %d\n", srcPortFound);
  printf("\tsrcIPFound: %d\n", srcIPFound);
  printf("\tdstPortFound: %d\n", dstPortFound);
  printf("\tdstIPFound: %d\n", dstIPFound);
 */

  /******* Determine if we encountered the beginning of the
    XML node
  *******/
  if( (nodeDepth == 1) && (strcmp((char*) nodeName, "rule") == 0) 
      && (nodeValue == NULL) && (xmlNodeHead == 0)) 
  {
    // printf("\n\t***** This is the beginning of the rule *****\n");
    // printf("\tA new node will be added to the list\n\n");
    xmlNodeHead = 1;
  }

  /******* Determine if we encountered uid & then save the uidcol
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "uid") == 0) 
      && (nodeValue == NULL) && (uidFound == 0)) {
    // printf("\t** uidcol has been found **\n\n");
    uidFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) && 
     (uidFound == 1) && (uid == NULL) )
  {
    // printf("\t** uidcol has been determined **\n");
    uid = malloc((sizeof(char) * strlen((char*)nodeValue)) +1);
    // uidFound=0;
    strncpy(uid, (char*)nodeValue, strlen((char*)nodeValue));
	uid[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** uidcol found to be: %s **\n\n", uid);
    return;
  }

  /******* Determine if we encountered coment & then save the coment
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "coment") == 0) 
      && (nodeValue == NULL) && (comentFound == 0)) {
    // printf("\t** coment has been found **\n\n");
    comentFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) && 
     (comentFound == 1) && (coment == NULL) )
  {
    // printf("\t** comentl has been determined **\n");
    coment = malloc((sizeof(char) * strlen((char*)nodeValue)) + 1);
    // comentFound=0;
    strncpy(coment, (char*)nodeValue, strlen((char*)nodeValue));
	coment[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** coment found to be: %s **\n\n", coment);
    return;
  }
  
  /******* Determine if we encountered proto & then save the protocol
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "proto") == 0) 
      && (nodeValue == NULL) && (protoFound == 0)) {
    // printf("\t** Protocol has been found **\n\n");
    protoFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) && 
     (protoFound == 1) && (proto == NULL) )
  {
    // printf("\t** Protocol has been determined **\n");
    proto = malloc((sizeof(char) * strlen((char*)nodeValue)) + 1);
    // protoFound=0;
    strncpy(proto, (char*)nodeValue, strlen((char*)nodeValue));
	proto[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** Protocol found to be: %s **\n\n", proto);
    return;
  }

  /******* Determine if we encountered ip version & then save version
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "ipv") == 0) 
      && (nodeValue == NULL) && (ipvFound == 0) )
  {
    // printf("\t** IP Version has been found **\n\n");
    ipvFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) 
     && (ipvFound == 1) && (ipv == NULL) ) 
  {
    // printf("\tIP version has been determined\n");
    ipv= malloc((sizeof(char) * strlen((char*)nodeValue))+1);
    // dstIPFound=0;
    strncpy(ipv, (char*)nodeValue, strlen((char*)nodeValue));
	ipv[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** IP Version found to be: %s **\n\n", ipv);
    return;
  }
  
  /******* Determine if we encountered source IP address & then 
           save source IP address
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "srcip") == 0) 
      && (nodeValue == NULL) && (srcIPFound == 0) ) 
  {
    // printf("\t** Source IP address has been found **\n\n");
    srcIPFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) 
     && (srcIPFound == 1) && (srcIP == NULL) ) 
  {
    // printf("\tSource IP address has been determined\n");
    srcIP = malloc((sizeof(char) * strlen((char*)nodeValue))+1);
    // srcIPFound=0;
    strncpy(srcIP, (char*)nodeValue, strlen((char*)nodeValue));
	srcIP[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** Source IP address  found to be: %s **\n\n", srcIP);
    return;
  }

  /******* Determine if we encountered source port & then save 
           source port
  *******/  
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "srcport") == 0) 
      && (nodeValue == NULL) && (srcPortFound == 0) ) 
  {
    // printf("\t** Source port address has been found **\n\n");
    srcPortFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) 
     && (srcPortFound == 1) && (srcPort == NULL) )
  {
    // printf("\tSource Port has been determined\n");
    srcPort = malloc((sizeof(char) * strlen((char*)nodeValue)) + 1);
    // srcIPFound=0;
    strncpy(srcPort, (char*)nodeValue, strlen((char*)nodeValue));
	srcPort[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** Source port found to be: %s **\n\n", srcPort);
    return;
  }


  /******* Determine if we encountered Destination IP address & then 
           save Destination IP address
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "dstip") == 0) 
      && (nodeValue == NULL) && (dstIPFound == 0) ) 
  {
    // printf("\t** Destination IP address has been found **\n\n");
    dstIPFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) 
     && (dstIPFound == 1) && (dstIP == NULL) )
  {
    // printf("\tDestination IP address has been determined\n");
    dstIP = malloc((sizeof(char) * strlen((char*)nodeValue))+1);
    // dstIPFound=0;
    strncpy(dstIP, (char*)nodeValue, strlen((char*)nodeValue));
	dstIP[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** Destination IP address  found to be: %s **\n\n", dstIP);
    return;
  }


  /******* Determine if we encountered Destination port & then save 
           destination port
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "dstport") == 0) 
      && (nodeValue == NULL) && (dstPortFound == 0) ) 
  {
    // printf("\t** Destination port address has been found **\n\n");
    dstPortFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) 
     && (dstPortFound == 1) && (dstPort == NULL) ) 
  {
    // printf("\tDestination Port has been determined\n");
    dstPort = malloc((sizeof(char) * strlen((char*)nodeValue))+1);
    // dstIPFound=0;
    strncpy(dstPort, (char*)nodeValue, strlen((char*)nodeValue));
	dstPort[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** Destination port found to be: %s **\n\n", dstPort);
    return;
  }

  /******* Determine if we encountered action & then save action
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "action") == 0) 
      && (nodeValue == NULL) && (actionFound == 0) ) {
    // printf("\t** action has been found **\n\n");
    actionFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) 
     && (actionFound == 1) && (action == NULL) ) 
  {
    // printf("\taction has been determined\n");
    action = malloc((sizeof(char) * strlen((char*)nodeValue))+1);
    // dstIPFound=0;
    strncpy(action, (char*)nodeValue, strlen((char*)nodeValue));
	action[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** action found to be: %s **\n\n", action);
    return;
  }


  /******* Determine if we should log the packet
  *******/
  if( (nodeDepth == 2) && (strcmp((char*) nodeName, "log") == 0) 
      && (nodeValue == NULL) && (logPacketFound == 0) ) {
    // printf("\t** Logging flag has been found **\n\n");
    logPacketFound=1;
    return;
  }
  if( (nodeDepth == 3) && (strcmp((char*) nodeName, "#text") == 0) 
     && (logPacketFound == 1) && (logPacket == NULL) ) 
  {
    // printf("\tIP version has been determined\n");
    logPacket = malloc((sizeof(char) * strlen((char*)nodeValue))+1);
    // dstIPFound=0;
    strncpy(logPacket, (char*)nodeValue, strlen((char*)nodeValue));
	logPacket[strlen((char*)nodeValue)] = '\0';
    // printf("\n\t** Packet logging flag found to be: %s **\n\n", logPacket);
    return;
  }

  /******* Determine if we encountered the end of the XML node, then:
     1) Invoke addToList()
     2) Increment ruleCount
     3) Free memory by calling destroyGlobs(0
     4) Reset error checking variables to 0, by calling initGlobs();
  *******/
  if( (nodeDepth == 1) && (strcmp((char*) nodeName, "rule") == 0) 
      && (nodeValue == NULL) && (xmlNodeHead == 1) && (protoFound == 1)
      && (srcPortFound == 1) && (srcIPFound == 1) && (dstPortFound == 1)
      && (dstIPFound == 1) && (ipvFound == 1) && (actionFound == 1)
      && (logPacketFound == 1) ) 
  {
    
    // printf("\n\t***** This is the end of the XML node *****\n");
    // printf("\tIncrementing variables\n\n");   
    // currNode = addToList(currNode, proto, ipv, srcIP, srcPort, dstIP, dstPort, 
               // action, logPacket, ruleCount);
               
    fwRuleNode * tmpNode;
    if( (tmpNode = malloc(sizeof(fwRuleNode))) == NULL) {
       printf("\n\tUnable to allocate memory for node addition");
    }
    else {
      printf("\n----- Storing informaiton into the new node -----\n");
      // Store ruleCount into location & ipv
      tmpNode->location = ruleCount;
      tmpNode->ipv = atoi(ipv);
      tmpNode->sPort = atoi(srcPort);
      tmpNode->dPort = atoi(dstPort);
      tmpNode->prev = NULL;
      tmpNode->next =  NULL;

      /*
      printf("\n\t tmpNode->location: %d\n", tmpNode->location);
      printf("\n\t tmpNode->ipv: %d\n", tmpNode->ipv);
      printf("\n\t tmpNode->sPort %d\n", tmpNode->sPort);
      printf("\n\t tmpNode->dPort %d\n", tmpNode->dPort);
      */


      // Allocate memory for storing uid
      if((tmpNode->uid = malloc(sizeof(char) * ((char) *uid) + 1)) == NULL) {
        printf("\n\taddToList - Unable to allocate memory for uid, exiting\n");
        exit(1);
      }
      else {
        // printf("\n\t Storing uid into the new node\n");
        strncpy(tmpNode->uid, uid, (sizeof(char) * (*uid)));
	tmpNode->uid[strlen(uid)] = '\0';
        // printf("\n\t tmpNode->uid: %s\n", tmpNode->uid);
      }

      // Allocate memory for storing coment
      if((tmpNode->coment = malloc(sizeof(char) * ((char) *coment) + 1)) == NULL) {
        printf("\n\taddToList - Unable to allocate memory for coment, exiting\n");
        exit(1);
      }
      else {
        // printf("\n\t Storing coment into the new node\n");
        strncpy(tmpNode->coment, coment, (sizeof(char) * (*coment)));
	tmpNode->coment[strlen(coment)] = '\0';
        // printf("\n\t tmpNode->coment: %s\n", tmpNode->coment);
      }      
    
      // Allocate memory for storing protocol
      if((tmpNode->proto = malloc(sizeof(char) * ((char) *proto)) + 1) == NULL) {
        printf("\n\taddToList - Unable to allocate memory for proto, exiting\n");
        exit(1);
      }
      else {
        // printf("\n\t Storing proto into the new node\n");
        strncpy(tmpNode->proto, proto, (sizeof(char) * (*proto)));
	tmpNode->proto[strlen(proto)] = '\0';
        // printf("\n\t tmpNode->proto: %s\n", tmpNode->proto);
      }

      // Allocate memory for storing srcIP
      if((tmpNode->srcIP = malloc(sizeof(char) * ((char) *srcIP))+1) == NULL) {
        printf("\n\taddToList - Unable to allocate memory for srcIP, exiting\n");
        exit(1);
      }
      else {
        // printf("\n\t Storing srcIP into the new node\n");
        strncpy(tmpNode->srcIP, srcIP, (sizeof(char) * (*srcIP)));
	tmpNode->srcIP[strlen(srcIP)] = '\0';
        // printf("\n\t tmpNode->srcIP: %s\n", tmpNode->srcIP);
      }    
    
      // Allocate memory for storing dstIP
      if((tmpNode->dstIP = malloc(sizeof(char) * ((char) *dstIP))+1) == NULL) {
        printf("\n\taddToList - Unable to allocate memory for dstIP, exiting\n");
        exit(1);
      }
      else {
        // printf("\n\t Storing dstIP into the new node\n");
        strncpy(tmpNode->dstIP, dstIP, (sizeof(char) * (*dstIP)));
	tmpNode->dstIP[strlen(dstIP)] = '\0';
        // printf("\n\t tmpNode->dstIP: %s\n", tmpNode->dstIP);
      }  

      // Allocate memory for storing action
      if((tmpNode->action = malloc(sizeof(char) * ((char) *action))+1) == NULL) {
        printf("\n\taddToList - Unable to allocate memory for action, exiting\n");
        exit(1);
      }
      else {
        // printf("\n\t Storing action into the new node\n");
        strncpy(tmpNode->action, action, (sizeof(char) * (*action)));
	tmpNode->action[strlen(action)] = '\0';
        // printf("\n\t tmpNode->action: %s\n", tmpNode->action);
      }

      // Allocate memory for storing log
      if((tmpNode->log = malloc(sizeof(char) * ((char) *logPacket))+1) == NULL) {
        printf("\n\taddToList - Unable to allocate memory for log, exiting\n");
        exit(1);
      }
      else {
        // printf("\n\t Storing log into the new node\n");
        strncpy(tmpNode->log, logPacket, (sizeof(char) * (*logPacket)));
	tmpNode->log[strlen(logPacket)] = '\0';
        // printf("\n\t tmpNode->log: %s\n", tmpNode->log);
      }    
      //addToList(&(*myList), &(*tmpNode));
      addToList(&(*myList), &(tmpNode));

      ruleCount++;
      // Release memory
      destroyGlobs();
      // Reset pointers to null
      initGlobs();
    }
    
  }

  // printf("\n\tProcessing rule #: %d\n\n", ruleCount);  
}

/************************************************************
  Validates XML documents against XML Schema
************************************************************/
int xmlrules_are_valid(const char *filename)
{
  int rc = 0;
  xmlParserCtxtPtr ctxt; /* the parser context */
  xmlDocPtr doc; /* the resulting document tree */

  /* create a parser context */
  ctxt = xmlNewParserCtxt();
  if (ctxt == NULL) {
    fprintf(stderr, "Failed to allocate parser context\n");
    exit(1);
  }
  /* parse the file, activating the DTD validation option */
  doc = xmlCtxtReadFile(ctxt, filename, NULL, XML_PARSE_DTDVALID);
  /* check if parsing suceeded */
  if (doc == NULL) {
    fprintf(stderr, "Failed to parse %s\n", filename);
  } 
  else {
    /* check if validation suceeded */
    if (ctxt->valid == 0) {
      fprintf(stderr, "Failed to validate:%s\n", filename);
      rc = 0;
    }
    if (ctxt->valid == 1) {
      fprintf(stderr, "Rules have been successfully validated %s\n", filename);
      rc = 1;
    }
    /* free up the resulting document */
	xmlFreeDoc(doc);
  }
  /* free up the parser context */
  xmlFreeParserCtxt(ctxt);

  return rc;
}




/************************************************************
  Process node sent from parseConfig - this function is repeatedly
  called by parseConfig to handle XML node data
************************************************************/
static void processNode(xmlTextReaderPtr reader,  fwRuleList **myList)
{
  // printf("<---- Executing processNode ----\n");

  xmlChar *name, *value;
  int depth;
    
  name = xmlTextReaderName(reader);
  depth = xmlTextReaderDepth(reader);

  /*
  printf("\tNode name is: %s\n", name);
  printf("\tNode depth is: %d\n", depth);
  */
    
  if (name == NULL) {
    name = xmlStrdup(BAD_CAST "--");
  }
    
  value = xmlTextReaderValue(reader);

  // printf("\tNode Value is: %s\n", value);
  // parseXML(depth, name, value, &(*sumNode));
  parseXML(depth, name, value, &(*myList));

  xmlFree(value);
  xmlFree(name);
}

/************************************************************
 This function can:
  1) Validate a XML document against a DTD, upon success it can
  2) Read the firewall rules from a XML file into a linked list
  3) The function expects:
     a) a pointer to a list, 
     b) a pointer to a node that should be head of the list
     c) a file name containing the rules in XML format
  The function parameters for the list and the nose are of type
  reference:
  
    parseConfig(char *fileName, fwRuleList **myList, fwRuleNode **head)

  The function should be called in the following manner:
  
    parseConfig(fileName, &(*myList), &(*head);
    
************************************************************/
int parseConfig(char *xmlRulesFile, fwRuleList **myfwRuleList, fwRuleNode **head) 
{
  int result = 0;
  int xmlValidated = 0;

  
  // Check if the file is readable
  result = access (xmlRulesFile, R_OK); 
  
  /******* 
     Call xmlrules_are_valid to ensure the ruleset file can be
     verified against the DTD
  *******/ 
  xmlValidated = xmlrules_are_valid(xmlRulesFile);
  
  
  if ( ( result == 0 ) && ( xmlValidated == 1) )
  {
    printf("%s File exists & readable - processing!!\n",xmlRulesFile);
    int ret;


    /******* Create list, head, etc for:
      1) Creating the list
      2) Initializing the list, etc
    *******/

    int r;
  
    //Setup list for firewall rules, parsed in from XML nodes
    if((*myfwRuleList = (fwRuleList *)malloc(sizeof(fwRuleList))) == NULL)
    {
      printf("List: Memory Allocation Failed...\n");
      exit(1);
    }
    if((*head = (fwRuleNode *)malloc(sizeof(fwRuleNode))) == NULL)
    {
      printf("Head: Memory Allocation Failed...\n");
      exit(1);
    }

    // Check the status of initializing the firewall rules 
    r = initFWRULES(&(**myfwRuleList), &(**head));
    if(r == -1)
    {
      printf("Linked List: initFWRULES() Failed...\n");
      exit(1);
    }

    /* call initGloba to zero out some variables used in tracking
       what has been found and located int the xml nodes */
    initGlobs();
  
  /** TO DO - xml Validation **/
    
    xmlTextReaderPtr reader = xmlNewTextReaderFilename(xmlRulesFile);
    
    if (reader != NULL) {
      ret = xmlTextReaderRead(reader);
      while (ret == 1) {
        processNode(reader, &(*myfwRuleList));
        ret = xmlTextReaderRead(reader);
      }
      xmlFreeTextReader(reader);
      if (ret != 0) {
        printf("%s : failed to parse\n", xmlRulesFile);
      }
      printList(*myfwRuleList);
    }
    else {
      printf("Unable to open %s\n", xmlRulesFile);
    }
    
    return 0;
  }
  else
  {
    printf("ERROR: %s doesn't exist or is not readble!\n",xmlRulesFile);
  }
  return 1;

}
